#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// Modification author: Hristo Hristov
// Modification date  : 24.05.2011 
// Modified Version   : 1.0
// Revision           : 5
// Description        : Modified version for NOVA as an abstract base class, 
//                      which contains all basic gameplay screen functionality
//                      and can be used to derive different game play screens.
//
// Modifications      : ### 24.05.2011 ###
//                      - This class contains a public scene, which can be 
//                        filled in the derived class. 
//                      - The pause method (when the pause button is pressed)
//                        can be defined in the derived class by using an event
//                        which is trigger by this class.
//
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using NOVA.ScreenManagement;
using NOVA.Scenery;
#endregion

namespace NOVA.ScreenManagement.BaseScreens
{
    /// <summary>
    /// This screen implements the basic gameplay screen logic. 
    /// </summary>
    public class GameplayScreen : GameScreen
    {
        #region Delegates
        /// <summary>
        /// A delegate/callback function that defines what to do when the pause button is pressed.
        /// </summary>
        public delegate void HandlePause();
        #endregion

        #region Events
        /// <summary>
        /// An event to add or remove a pause method
        /// </summary>
        public event HandlePause OnPause;
        #endregion

        #region Members

        ContentManager m_content;
        SpriteFont m_gameFont;
        Scene m_scene;
        
        float pauseAlpha;



        private QuadRenderComponent quadRenderer;

        private RenderTarget2D colorRT; //color and specular intensity
        private RenderTarget2D normalRT; //normals + specular power
        private RenderTarget2D depthRT; //depth
        private RenderTarget2D lightRT; //lighting

        private Effect clearBufferEffect;
        private Effect directionalLightEffect;

        private Effect pointLightEffect;
        private Model sphereModel; //point ligt volume

        private Effect finalCombineEffect;

        private Vector2 halfPixel;

        #endregion

        #region Properties
        public Scene Scene 
        { 
            get { return m_scene; }
            set { m_scene = value; }
        }
        #endregion

        #region Initialization

        /// <summary>
        /// Constructor.
        /// </summary>
        public GameplayScreen()
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);
            
            m_scene = new Scene(Core.Game, Core.Graphics);
        }

        /// <summary>
        /// Initializes the scene
        /// </summary>
        public override void Initialize()
        {
            
            m_scene.Initialize();
            m_scene.LoadContent();
        }

        /// <summary>
        /// Load graphics content for the game.
        /// </summary>
        public override void LoadContent()
        {
            if (m_content == null)
                m_content = new ContentManager(ScreenManager.Game.Services, "Content");

            m_gameFont = Core.GameFont;//m_content.Load<SpriteFont>("gamefont");
                       
            
            // once the load has finished, we use ResetElapsedTime to tell the game's
            // timing mechanism that we have just finished a very long frame, and that
            // it should not try to catch up.
            ScreenManager.Game.ResetElapsedTime();
        }

        /// <summary>
        /// Unload graphics content used by the game.
        /// </summary>
        public override void UnloadContent()
        {
            if (m_content != null)
            {
                m_content.Unload();

                m_content.Dispose();
            }
        }

        #endregion
        
        #region Update and Draw


        /// <summary>
        /// Updates the state of the game. This method checks the GameScreen.IsActive
        /// property, so the game will stop updating when the pause menu is active,
        /// or if you tab away to a different application.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, false);

            // Gradually fade in or out depending on whether we are covered by the pause screen.
            if (coveredByOtherScreen)
                pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1);
            else
            {
                pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0);

                m_scene.Update(gameTime);
            }
        }


        /// <summary>
        /// Lets the game respond to player input. Unlike the Update method,
        /// this will only be called when the gameplay screen is active.
        /// </summary>
        public override void HandleInput(InputState input)
        {
            if (input == null)
                throw new ArgumentNullException("input");

            // Look up inputs for the active player profile.
            int playerIndex = (int)ControllingPlayer.Value;

            KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex];
            GamePadState gamePadState = input.CurrentGamePadStates[playerIndex];

            // The game pauses either if the user presses the pause button, or if
            // they unplug the active gamepad. This requires us to keep track of
            // whether a gamepad was ever plugged in, because we don't want to pause
            // on PC if they are playing with a keyboard and have no gamepad at all!
            bool gamePadDisconnected = !gamePadState.IsConnected &&
                                       input.GamePadWasConnected[playerIndex];

            if (input.IsPauseGame(ControllingPlayer) || gamePadDisconnected)
                if(OnPause != null)
                    OnPause();
        }


        /// <summary>
        /// Draws the gameplay screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            // This game has a blue background. Why? Because!
            //ScreenManager.GraphicsDevice.Clear(ClearOptions.Target, Color.Black, 0, 0);            
            
            // If the game is transitioning on or off, fade it out to black.
            if (TransitionPosition > 0 || pauseAlpha > 0)
            {
                float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);

                ScreenManager.FadeBackBufferToBlack(alpha);
            }
            //else
                m_scene.Draw(gameTime);            
        }                

        #endregion

        public override void Dispose()
        {
            m_scene.Dispose();           

            base.Dispose();
        }
    }
}